home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / PostScriptFiles / FontHandlerProcs.ps < prev    next >
Encoding:
Text File  |  2000-09-28  |  13.3 KB  |  512 lines  |  [TEXT/MPS ]

  1. %
  2. %    File:        FontHandlerProcs.ps
  3. %
  4. %    Version:    Technology:    Quickdraw GX 1.1.x.
  5. %
  6. %    Copyright:    © 1991-7 by Apple Computer, Inc., all rights reserved.
  7. %
  8. %
  9. %
  10. %    This file contains PostScript procedures for the font handler
  11. %
  12.  
  13. /FHSaveLevel null def
  14.  
  15. %
  16. %
  17. %        Procedure DoSave:
  18. %    
  19. %            Procedure saves the current VM sate.
  20. %
  21. /DoSave {
  22.  
  23.     /FHSaveLevel save def
  24.  
  25. } bind def
  26.  
  27.  
  28. %
  29. %
  30. %    Procedure DoRestore
  31. %
  32. %        Procedure restores to the saved VM state.
  33. %        Maintains the current point if there was one.
  34. /DoRestore {
  35.  
  36.     /currentpoint                    % Maintain the current-point because IE can't restore it easily.
  37.     load stopped not            %  There might not be a current point.
  38.  
  39.     dup {                                    %        But, if there was, make sure we can keep it the same after the restore.
  40.                                                 %            Stack is x y bool
  41.         3 1 roll                        %            Move the current point to top of stack.    
  42.         transform                        %            So transform it to device space since the restore can change the CTM.
  43.         3 -1 roll                        %            Stack is x' y' bool
  44.     
  45.     } if
  46.     
  47.     FHSaveLevel restore        % Do the restore.
  48.     
  49.     {                                % If there was a current point, it is on stack in device space.
  50.  
  51.         itransform        %        Put it into space of CTM
  52.         moveto                %        move there.
  53.         
  54.     } if
  55.  
  56. } bind def
  57.  
  58.  
  59.  
  60. %<FF>
  61. %
  62. %        Routine:    HexDigitToInt
  63. %        Routine takes the ascii value of a hex digit (0-9, A-F, a-f) and returns the integer (0-15)
  64. %
  65. %        ascii-digit HexDigitToInt int
  66. %
  67. /HexDigitToInt {
  68.  
  69.     % Stack is next byte of name:
  70.  
  71.     dup 57 le {                                    % If it is less than or equal to '9', must be a 0-9
  72.         48 sub                                        %     subtract 48 (0)
  73.     } {                                                    % else
  74.         dup 70 le {                                %        If it is less than or equal to 'F', must be an A-F
  75.             55  sub                                    %            subtract 65 (A) add 10
  76.         } {                                                %        else must be a-f
  77.             87 sub                                    %            subtract 97 (a) add 10
  78.         } ifelse
  79.     } ifelse
  80.  
  81. } bind def
  82.  
  83. %
  84. %        Routine: HexNameToBytes
  85. %        Routine takes a name that is a string of hex bytes
  86. %        and makes it into a string such that each byte
  87. %        of the string is the converted hex value.
  88. %
  89. %        /a01AF yields <01AF>
  90. %
  91. %        name HexNameToBytes string
  92. %
  93. /HexNameToBytes {
  94.  
  95.     nameString cvs                                            % Convert the name to a string.
  96.     /nameLength exch length 1 sub def        % Store the length of the substring in here. (-1 for leading "a")
  97.     nameString 1 nameLength getinterval    % Get the string without the leading "a"
  98.     /tempString exch def                                % Put it in tempString, processing will be on tempString.
  99.         
  100.     % Loop over the string
  101.     0 1 nameLength 1 sub {                % Loop from zero to length-1
  102.          
  103.         tempString exch get                    % Get the next digit ou;t of the string.
  104.         HexDigitToInt                                % Convert the digit to an integer, leave it on the stack.
  105.     
  106.     } for
  107.  
  108.     % Stack is now:  digit0, …, digitN
  109.  
  110.     %
  111.     %        Now put the bytes for the hex digits back into the string
  112.     %
  113.     nameLength 2 idiv 1 sub -1 0 {        % Loop for number of bytes, indexing backwards since digits are on stack
  114.     
  115.         % Stack is: next 2 digits, index
  116.         
  117.         3 1 roll                        % Stack is: index, next 2 digits.
  118.         exch 16 mul add            % Convert the two digits into a byte.
  119.                                                 % Stack is: index byte
  120.         tempString 3 1 roll
  121.         put                                    % Put the byte into the string at the index position.
  122.     
  123.     } for
  124.  
  125.     tempString 0 nameLength 2 idiv getinterval
  126.         
  127. } bind def
  128.  
  129.  
  130. %
  131. %        The BuiildChar procedure for "reencoded" composite fonts:
  132. %        Converts the glyph names into a 1 or 2 byte string to 
  133. %        "show" from the base composite font.
  134. %        The glyph names must have been generated from a 'post' table
  135. %        format 4 or this won't work at all.
  136. %
  137. /ReEncodedCompositeBuildChar {
  138.  
  139.     GXFontDict begin                        % This buildchar Uses definitions in here
  140.  
  141.         exch begin
  142.         
  143.             LocalVariables begin
  144.         
  145.                 Encoding exch get                % Get the name for this character out of encoding.
  146.                 baseFontDict setfont        % Make the base composite font the current font.
  147.                 HexNameToBytes                    % Convert the name into a string, leave on stack.
  148.                 
  149.                 dup stringwidth                    % Get the advance metrics of the character on the stack.
  150.                 setcharwidth                        % Set up the font cache with metrics            
  151.                 0 0 moveto show                    % Actually draw the character.
  152.                             
  153.             end
  154.         
  155.         end
  156.     
  157.     end
  158.  
  159.  
  160. } bind def
  161.  
  162. %
  163. %
  164. %    Procedure:  ReEncodeCompositeFont
  165. %
  166. %        Procedure makes a new font that is a re-encoding of a composite font (type-0)
  167. %        In order for this to work, the Encoding vectors must contain names that are the
  168. %        hex strings of the character codes for the glyph in question (preceeded by leading "a") as 
  169. %        defined by the 'post' table type 4.
  170. %        For example character code 257 would have name /a0101, character 15 would have name /a0F
  171. %
  172. %
  173. %        newName fixSeac encoding fontDict ReEncodeCompositeFont -
  174. %                newName:                    The name to give the re-encoded font.
  175. %                fixSEAC:                    Boolean, true if we should fix up the encoding for SEAC characters.
  176. %                encoding:                    An array containing the encoding vector.
  177. %                fontDict:                    font dictionary of font to re-encode.
  178. /ReEncodeCompositeFont {
  179.  
  180.     10 dict begin
  181.  
  182.         1 scalefont /baseFontDict exch def            % Make a 1 point base font for buildChar.
  183.         /Encoding exch def                                            % Grab the encoding.
  184.         pop                                                                            % pop off fixSEAC, it means nothing here.
  185.         
  186.         /FontMatrix matrix def
  187.         /FontBBox [0 0 0 0] def
  188.         
  189.         /FontType 3 def
  190.         
  191.         /BuildChar /ReEncodedCompositeBuildChar load def
  192.         
  193.         /LocalVariables 3 dict dup begin
  194.             /nameString 5 string def            % 4 bytes allows for 2 byte character codes in hex. (plus one for leading "a")
  195.             /nameLength 0 def                            % The length of the encoding name will be stored in here.
  196.             /tempString 4 string def            % 4 bytes for hex portion of name, also used for show.
  197.         end def
  198.         
  199.  
  200.         currentdict             % Leave a copy of the dictionary on the stack for definefont
  201.     end
  202.     
  203.     definefont pop            
  204.  
  205. } bind def
  206.  
  207.  
  208.  
  209.  
  210. %<FF>
  211. %
  212. %
  213. %            Code to deal with SEAC (Standard Encoding Accented Characters) fonts
  214. %            The Problem:
  215. %                Fonts that use SEAC on PS versions <= 49.0 require that any components
  216. %                of an accented character that uses SEAC be in the encoding vector as well
  217. %                as the composite character itself.
  218. %            
  219. %            This code is a heuristic hack!!  Unfortunately, there is no other way to deal with it.
  220. %            It depends on the following assumptions:
  221. %
  222. %            1.        The AccentNames array contains all of the accent characters that may be used by a 
  223. %                                SEAC font.
  224. %
  225. %            2.        That the names of glyphs that use SEAC are the names of the indivicual characters
  226. %                                combined.  For example Ccedilla is the C and the cedilla characters.
  227. %
  228. %
  229. /AccentNames [
  230.  
  231.     (acute)
  232.     (grave)
  233.     (circumflex)
  234.     (cedilla)
  235.     (ring)
  236.     (tilde)
  237.     (dieresis)
  238.     (caron)
  239.  
  240. ] def
  241.  
  242. /GlyphNameString 255 string def
  243. /EncodingIndex 0 def
  244. /FreeEncodingIndex 0 def
  245. /FoundName false def
  246.  
  247. %
  248. %        Function:    AddToEncoding
  249. %
  250. %            Function takes a name on the stack and puts it in an empty spot
  251. %            in the encoding if it isn't there already
  252. %
  253. %            name AddToEncoding -
  254. %
  255. /AddToEncoding {
  256.  
  257.     /EncodingIndex 0 store                    %    Initialize the index.
  258.     /FoundName false store                    %    Initialize this too.
  259.     /FreeEncodingIndex -1 store            % Sentinal, uninitialized.
  260.     
  261.     %
  262.     %        Search the encoding vector for a match or a free spot.
  263.     %
  264.     Encoding {
  265.  
  266.         % Stack is: name, Encoding-name
  267.     
  268.         dup /.notdef eq {        %        If we hit a .notdef and index isn't zero, save as an available spot
  269.         
  270.             EncodingIndex 0 ne {        % If the index wasn't zero, save this position away as an available spot.
  271.                 /FreeEncodingIndex 
  272.                 EncodingIndex store
  273.             } if
  274.             pop                                %     Pop off the duplicate of the encoding name.
  275.         
  276.         } {                                    %    Else See if the name matches
  277.                                                 %        Stack is: name, Encoding-name
  278.             1 index eq {            %        If they match:
  279.                     /FoundName true store    % Note that we found match
  280.                     exit                    %            Exit the loop
  281.             } if
  282.  
  283.         } ifelse
  284.         
  285.         /EncodingIndex EncodingIndex 1 add store            % Increment the index
  286.         
  287.     } forall
  288.     
  289.     FoundName not {                % If we didn't find the name, put it in the encoding at the first available spot.
  290.     
  291.         FreeEncodingIndex -1 ne {                                            %    If we found a free spot
  292.             Encoding exch FreeEncodingIndex exch put        %        Put the name in the encoding at the free location.
  293.         } {                                                                                        % else
  294.             (Couldn't find empty spot in encoding) ==        %        Notify this condition.
  295.         } ifelse
  296.     
  297.     } {                                        % Else
  298.     
  299.         pop                                    %        pop off the name.
  300.     
  301.     } ifelse
  302.  
  303. } bind def
  304.  
  305.  
  306. %
  307. %    EncodeAccentedCharacter:
  308. %        Function checks to see if a glyph name is an accented character
  309. %            If it is it makes sure to add the components to the encoding vector
  310. %             if they are not already there.
  311. %
  312. %        Precondision, the font dictionary is on the dictionary stack.
  313. %
  314. %        name EncodeAccentedCharacter -
  315. %
  316. /EncodeAccentedCharacter {
  317.  
  318.     GlyphNameString cvs                    % Convert the glyph name to a string, leave it on the stack.
  319.     
  320.     %
  321.     %    Loop through the array of accent names, see if the name is an accented character
  322.     %
  323.     
  324.     AccentNames {            
  325.     
  326.         % Stack is now: glyph-name, accent-name
  327.         
  328.         1 index exch            % Stack is now: glyph-name, glyph-name, accent-name
  329.         
  330.         search {                    % If the glyph name contained the accent name.
  331.                                             %        Stack is now: glyph-name, post, accent-name, pre
  332.             3 -1 roll                %        Stack is now: glyph-name, accent-name, pre, post
  333.             length 0 eq {        %        If the length of the post was zero, then we found an accented character
  334.             
  335.                                             %            Stack is now: glyph-name, accent-name, pre
  336.                 cvn exch cvn    %            Convert those strings to names
  337.                 AddToEncoding    %            The pre string is the character that is accented, add it to the encoding
  338.                 AddToEncoding    %            Add the accent-name to the encoding
  339.                 exit                    %            Exit the loop
  340.                 
  341.             } {                            %        Else
  342.                 pop pop                %            Pop off the accent-na,e and the pre - not a valid match
  343.             } ifelse
  344.         
  345.         } {                                % Else
  346.             pop                            %     If no match, pop off the copy of the string left by search
  347.         } ifelse
  348.     
  349.     } forall
  350.     
  351.     pop                    % Pop off the copy of the glyph name string.
  352.  
  353. } bind def
  354.  
  355.  
  356. %
  357. %        Procedure FixSEAC:
  358. %
  359. %        Procedure takes a font dictionary and resolves any SEAC problems.
  360. %
  361. %        font-dictionary FixSEAC font-dictionary'
  362. %
  363. /FixSEAC {
  364.  
  365.     dup begin                    % Put the font dictionary on the dict stack
  366.  
  367.         Encoding {            %    Loop through the encoding vector
  368.         
  369.             EncodeAccentedCharacter            % Fix the character.
  370.         
  371.         } forall
  372.  
  373.     end
  374.  
  375. } bind def
  376.  
  377.  
  378.  
  379. %<FF>
  380. %
  381. %        Procedure ReEncodeNormalFont:
  382. %
  383. %            Procedure Re-encodes a non-coposite font.
  384. %
  385. %            newName fixSEAC encoding fontName ReEncodeFont -
  386. %
  387. %                newName:                    The name to give the re-encoded font.
  388. %                fixSEAC:                    Boolean, true if we should fix up the encoding for SEAC characters.
  389. %                encoding:                    An array containing the encoding vector.
  390. %                fontDict:                    font dictionary of font to re-encode.
  391. %            
  392. /ReEncodeNormalFont {
  393.  
  394.     dup length                                % Get the size of the font dictionary.        
  395.     dict                                             % Make a dictionary for the new font
  396.     
  397.     %
  398.     %    Duplicate all entries from the base font except the FID.
  399.     %
  400.     exch                                        % stick the base font dict on top of operand stack
  401.     {
  402.         exch dup /FID ne             % Copy entry if it is not FID.
  403.             {    
  404.                 2 index                        % Copy the new dict to top of operand stack, stack is (dict key val dict)
  405.                 4 1 roll                    % Make stack (dict dict value key)
  406.                 exch
  407.                 put                                % Copy the value, the new dict is still on the stack
  408.             }
  409.             {pop pop}                        % Don't duplicate the FID
  410.             ifelse
  411.     } forall
  412.     
  413.     % the new dictionary is on the stack.
  414.     
  415.     dup                            % Stack is: name fixSEAC encoding dict dict
  416.     3 -1 roll                % Stack is: name fixSEAC dict dict encoding
  417.     /Encoding exch    % Stack is: name fixSEAC dict dict /Encoding encoding
  418.     put                            % stack is: name fixSEAC dict
  419.     
  420.     %
  421.     %        If we need to fix SEAC, do it
  422.     %
  423.     exch {                    % if fixSEAC
  424.     
  425.         dup /FontType get 4 eq                                            % If the font type is 4 (font-folio fonts)
  426.         version    cvr 49.0 le                                                    % if version is <= 49.0, SEAC (bug was fixed after this according to Gayle Tyson @ Adobe)
  427.         or {                                                                                % If either of the above is true
  428.             FixSEAC                                                                        %        fix SEAC encoding.
  429.         } if
  430.         
  431.     } if
  432.     
  433.     definefont pop
  434.     
  435. } bind def
  436.  
  437.  
  438.  
  439. %<FF>
  440. %
  441. %        Procedure ReEncodeFont:
  442. %
  443. %            Procedure Re-encodes a non-coposite font.
  444. %
  445. %            newName fixSEAC encoding fontName ReEncodeFont -
  446. %
  447. %                newName:                    The name to give the re-encoded font.
  448. %                fixSEAC:                    Boolean, true if we should fix up the encoding for SEAC characters.
  449. %                encoding:                    An array containing the encoding vector.
  450. %                fontName:                    The name of the font to re-encode.
  451. %            
  452. /ReEncodeFont {
  453.  
  454.     findfont dup /FontType get 0 eq {
  455.  
  456.         ReEncodeCompositeFont    
  457.     
  458.     } {
  459.  
  460.         ReEncodeNormalFont    
  461.     
  462.     } ifelse
  463.  
  464. } bind def
  465.  
  466.  
  467.  
  468.  
  469.  
  470. %<FF>
  471. %
  472. %            Procedure        MakeCompositeFont
  473. %
  474. %            Procedure takes an array of font objects and makes a composite font out of them.
  475. %            The resulting font will take 2-byte strings in "show" operations such that the
  476. %            first byte is which font to use and the second byte is which character
  477. %            This will allow creating single fonts with up to 65536 glyphs.
  478. %
  479. %            fontArray newName MakeCompositeFont -
  480. %
  481. /MakeCompositeFont {
  482.  
  483.     6 dict begin                                % Make a dictionary for the composite font.
  484.  
  485.         /FontName exch def                % Get the name for the composite font.
  486.         
  487.         dup length /numFonts exch def        % Cache the number of fonts
  488.         
  489.         /FontType 0 def                        % Font is type zero.
  490.         /FMapType 2 def                        % FMapType 2 means first byte is index into Encoding for font, 2nd is character to draw.
  491.         /FDepVector exch def            % The array of fonts passed in is the FDepVector.
  492.  
  493.         /FontMatrix matrix def        % The Font matrix is identity, base fonts have real information.
  494.  
  495.         % Create the encoding which is just an array with elements as integers 0 to N-1 where N is # of fonts in FDepVector
  496.         %        example:  [0 1 2 3] for 4 fonts.
  497.         
  498.         /Encoding numFonts array def
  499.         
  500.         0 1 numFonts 1 sub {
  501.  
  502.             Encoding exch dup        % Stack is: Encoding index index
  503.             put                                    % Put index into encoding at position index.
  504.         
  505.         } for
  506.  
  507.         FontName currentdict definefont pop
  508.         
  509.     end
  510.         
  511. } bind def
  512.